package v1

import (
	"io/ioutil"
	"net/http"
	"strconv"
	"toy-car/models"
	"toy-car/pkg/e"
	"toy-car/pkg/util"

	"github.com/gin-gonic/gin"
	"github.com/unknwon/com"
)

// @Tags ExaFileUploadAndDownload
// @Summary 上传文件示例
// @Security ApiKeyAuth
// @accept multipart/form-data
// @Produce  application/json
// @Param file formData file true "上传文件示例"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"上传成功"}"
// @Router /fileUploadAndDownload/upload [post]
func FileUpload(c *gin.Context) {
	var file models.ExaFileUploadAndDownload
	noSave := c.DefaultQuery("noSave", "0")
	_, header, err := c.Request.FormFile("file")

	err, file = models.UploadFile(header, noSave) // 文件上传后拿到文件路径

	code := e.SUCCESS
	if err != nil {
		code = e.ERROR
	}

	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  e.GetMSG(code),
		"data": file,
	})
}

// @Tags ExaFileUploadAndDownload
// @Summary 分页文件列表
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.PageInfo true "页码, 每页大小"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /fileUploadAndDownload/getFileList [post]
func FileListFetch(c *gin.Context) {
	page, pageSize := util.GetPageAndSize(c)
	err, list, total := models.GetFileRecordInfoList(page, pageSize)
	data := make(map[string]interface{})
	code := e.SUCCESS
	if err != nil {
		code = e.ERROR
	}
	data["page"] = page
	data["pageSize"] = pageSize
	data["data"] = list
	data["total"] = total
	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  e.GetMSG(code),
		"data": data,
	})
}

// @Tags ExaFileUploadAndDownload
// @Summary 删除文件
// @Security ApiKeyAuth
// @Produce  application/json
// @Param data body model.ExaFileUploadAndDownload true "传入文件里面id即可"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
// @Router /fileUploadAndDownload/deleteFile [post]
func FileDelete(c *gin.Context) {
	id := com.StrTo(c.Param("id")).MustInt()

	data := make(map[string]interface{})
	code := e.SUCCESS

	// todo 比对删除自己，返回错误
	err := models.DeleteFile(id)
	if err != nil {
		code = e.ERROR
	}

	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  e.GetMSG(code),
		"data": data,
	})
}

// @Tags ExaFileUploadAndDownload
// @Summary 断点续传到服务器
// @Security ApiKeyAuth
// @accept multipart/form-data
// @Produce  application/json
// @Param file formData file true "an example for breakpoint resume, 断点续传示例"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"切片创建成功"}"
// @Router /fileUploadAndDownload/breakpointContinue [post]
func FilebreakpointUpload(c *gin.Context) {
	fileMd5 := c.Request.FormValue("fileMd5")
	fileName := c.Request.FormValue("fileName")
	chunkMd5 := c.Request.FormValue("chunkMd5")
	chunkNumber := com.StrTo(c.Request.FormValue("chunkNumber")).MustInt()
	chunkTotal := com.StrTo(c.Request.FormValue("chunkTotal")).MustInt()
	_, FileHeader, err := c.Request.FormFile("file")

	code := e.SUCCESS
	if err != nil {
		code = e.ERROR
	} else {
		f, err := FileHeader.Open()
		if err != nil {
			code = e.ERROR
			return
		}
		defer f.Close()
		cen, _ := ioutil.ReadAll(f)
		if !util.CheckMd5(cen, chunkMd5) {
			code = e.ERROR
		} else {
			err, file := models.FindOrCreateFile(fileMd5, fileName, chunkTotal)
			if err != nil {
				code = e.ERROR
			} else {
				err, pathc := util.BreakPointContinue(cen, fileName, chunkNumber, chunkTotal, fileMd5)
				if err != nil {
					code = e.ERROR
				} else {
					if err = models.CreateFileChunk(uint(file.ID), pathc, chunkNumber); err != nil {
						code = e.ERROR
					}
				}
			}
		}
	}
	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  e.GetMSG(code),
		"data": c,
	})
}

// @Tags ExaFileUploadAndDownload
// @Summary 查找文件
// @Security ApiKeyAuth
// @accept multipart/form-data
// @Produce  application/json
// @Param file formData file true "Find the file, 查找文件"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查找成功"}"
// @Router /fileUploadAndDownload/findFile [post]
func FileSearch(c *gin.Context) {
	fileMd5 := c.Query("fileMd5")
	fileName := c.Query("fileName")
	chunkTotal, _ := strconv.Atoi(c.Query("chunkTotal"))
	err, file := models.FindOrCreateFile(fileMd5, fileName, chunkTotal)
	code := e.SUCCESS
	if err != nil {
		code = e.ERROR
	}
	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  e.GetMSG(code),
		"data": file,
	})
}

// @Tags ExaFileUploadAndDownload
// @Summary 创建文件
// @Security ApiKeyAuth
// @accept multipart/form-data
// @Produce  application/json
// @Param file formData file true "上传文件完成"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"file uploaded, 文件创建成功"}"
// @Router /fileUploadAndDownload/findFile [post]
func FilebreakpointFinish(c *gin.Context) {
	fileMd5 := c.Query("fileMd5")
	fileName := c.Query("fileName")
	err, filePath := util.MakeFile(fileName, fileMd5)
	code := e.SUCCESS
	if err != nil {
		code = e.ERROR
	}
	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  e.GetMSG(code),
		"data": filePath,
	})
}

// @Tags ExaFileUploadAndDownload
// @Summary 删除切片
// @Security ApiKeyAuth
// @accept multipart/form-data
// @Produce  application/json
// @Param file formData file true "删除缓存切片"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"缓存切片删除成功"}"
// @Router /fileUploadAndDownload/removeChunk [post]
func FilebreakpointDelete(c *gin.Context) {
	fileMd5 := c.Query("fileMd5")
	fileName := c.Query("fileName")
	filePath := c.Query("filePath")
	err := util.RemoveChunk(fileMd5)
	err = models.DeleteFileChunk(fileMd5, fileName, filePath)
	code := e.SUCCESS
	if err != nil {
		code = e.ERROR
	}
	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  e.GetMSG(code),
		"data": true,
	})
}
